package com.wtzz.police.base.controller;

import com.wtzz.police.base.model.enums.WtzzResponse;
import com.wtzz.police.base.model.exception.WtzzConstraintException;
import com.wtzz.police.base.model.exception.WtzzNoRecordException;
import com.wtzz.police.base.model.exception.WtzzRuntimeException;
import com.wtzz.police.base.model.response.ResponseBean;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.persistence.PersistenceException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.net.ConnectException;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 报错控制器
 */
@RestControllerAdvice(annotations = {RestController.class, Controller.class})
public class SpringExceptionHandle {

    private static final Logger logger = LoggerFactory.getLogger(SpringExceptionHandle.class);

    private <T> ResponseBean<T> returnResponse(boolean success, String code, String message) {
        return new ResponseBean<>(success, code, message);
    }

    private <T> ResponseBean<T> returnResponse(boolean success, WtzzResponse resp) {
        return new ResponseBean<>(success, resp.getCode(), resp.getMsg());
    }

    private <T> ResponseBean<T> returnResponse(boolean success, WtzzResponse resp, String message) {
        return new ResponseBean<>(success, resp.getCode(), resp.getMsg() + (StringUtils.isNotEmpty(message) ? ":" + message : ""));
    }

    private <T> ResponseBean<T> returnResponse(boolean success, WtzzRuntimeException exception) {
        return new ResponseBean<>(success,
                exception.getCode(),
                exception.getMsg() + (StringUtils.isNotEmpty(exception.getMessage()) && exception.getMessage() != exception.getMsg() ? ":" + exception
                        .getMessage() : ""));
    }

//	/**
//	 * 请求参数类型错误异常的捕获
//	 * @param e
//	 * @return
//	 */
//	@ExceptionHandler(value={BindException.class})
//	@ResponseBody
//	@ResponseStatus(value=HttpStatus.BAD_REQUEST)
//	public ResponseBean<String> badRequest(BindException e){
//		logger.error("occurs error when execute method ,message {}",e.getMessage());
//		return new ResponseBean<>(false, WtzzResponseEnums.BAD_REQUEST);
//	}

//	/**
//	 * 404错误异常的捕获
//	 * @param e
//	 * @return
//	 */
//	@ExceptionHandler(value={NoHandlerFoundException.class})
//	@ResponseBody
//	@ResponseStatus(value=HttpStatus.NOT_FOUND)
//	public ResponseBean<String> badRequestNotFound(BindException e){
//		logger.error("occurs error when execute method ,message {}",e.getMessage());
//		return new ResponseBean<>(false,null, WtzzResponseEnums.NOT_FOUND);
//	}
// 

    /**
     * @param e
     * @return
     */
    @ExceptionHandler(AuthenticationException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
    public ResponseBean<String> authentication(AuthenticationException e) {
        logger.info("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isInfoEnabled()) logger.info(e.getMessage(), e);
        return returnResponse(false, WtzzResponse.AUTHENTICATION_FAILED.getCode(), e.getMessage());
    }

    /**
     * @param e
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.FORBIDDEN)
    public ResponseBean<String> authentication(AccessDeniedException e) {
        logger.info("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isInfoEnabled()) logger.info(e.getMessage(), e);
        return returnResponse(false, WtzzResponse.ACCESS_DENIED, e.getMessage());
    }

    /**
     * 自定义异常的捕获
     * 自定义抛出异常。统一的在这里捕获返回JSON格式的友好提示。
     *
     * @param exception
     * @param request
     * @return
     */
    @ExceptionHandler(value = {WtzzRuntimeException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public <T> ResponseBean<T> sendError(WtzzRuntimeException exception, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        logger.info("occurs error when execute url ={} ,message {}", requestURI, exception.getMsg());
        if (logger.isInfoEnabled()) logger.info(exception.getMessage(), exception);
        return returnResponse(false, exception);
    }

    /**
     * 数据库操作出现异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {SQLException.class, DataAccessException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseBean<String> systemError(Exception e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        return returnResponse(false, WtzzResponse.DATABASE_ERROR);
    }

    /**
     * 网络连接失败！
     *
     */
    @ExceptionHandler(value = {ConnectException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseBean<String> connect(Exception e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        return returnResponse(false, WtzzResponse.CONNECTION_ERROR);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ResponseBean<String> baseRequest(ConstraintViolationException e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        return returnResponse(false, WtzzResponse.ILLEGAL_ARGUMENT, e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ResponseBean<String> baseRequest(MethodArgumentNotValidException e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        BindingResult bindingResult = e.getBindingResult();
        String message = bindingResult.getFieldError().getDefaultMessage();
        return returnResponse(false, WtzzResponse.ILLEGAL_ARGUMENT, message);
    }


    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ResponseBean<String> baseRequest(HttpMessageNotReadableException e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        return returnResponse(false, WtzzResponse.ILLEGAL_ARGUMENT, "没有请求数据");
    }

    @ExceptionHandler(value = {Exception.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseBean<String> notAllowed(Exception e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        return returnResponse(false, WtzzResponse.SYSTEM_ERROR, e.getMessage());
    }

    @ExceptionHandler(PersistenceException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ResponseBean<String> baseRequest(PersistenceException e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        String message = e.getMessage();
        Throwable cause = e.getCause();
        if (cause instanceof org.hibernate.exception.ConstraintViolationException) {
            String detailMessage = getConstraintViolationExceptionMessage((org.hibernate.exception.ConstraintViolationException) cause);
            if (detailMessage != null) {
                message = detailMessage;
            }
        }
        return returnResponse(false, WtzzResponse.ILLEGAL_ARGUMENT.getCode(), message);
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ResponseBean<String> baseRequest(DataIntegrityViolationException e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        String message = e.getRootCause().getMessage();
        Throwable cause = e.getCause();
        if (cause instanceof org.hibernate.exception.ConstraintViolationException) {
            String detailMessage = getConstraintViolationExceptionMessage((org.hibernate.exception.ConstraintViolationException) cause);
            if (detailMessage != null) {
                message = detailMessage;
            }
        }
        return returnResponse(false, WtzzResponse.ILLEGAL_ARGUMENT.getCode(), message);
    }

    private String getConstraintViolationExceptionMessage(org.hibernate.exception.ConstraintViolationException e) {
        String message = null;
        String constraintName = e.getConstraintName();
        if (constraintName != null) {
            if (constraintName.startsWith("unique_")) {
                message = "部分提交的值已存在";
                try {
                    String[] parts = constraintName.split("_");
                    String item = "";
                    String column = "";
                    if ("department".equals(parts[1])) {
                        item = "机构";
                    } else if ("user".equals(parts[1])) {
                        item = "用户";
                    }
                    if ("username".equals(parts[2]) || "name".equals(parts[2])) {
                        column = "名";
                    } else if ("code".equals(parts[2])) {
                        column = "编码";
                    } else if ("phone".equals(parts[2])) {
                        column = "手机号";
                    }
                    return item + column + "已存在";
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        } else {
            Pattern p = Pattern.compile("Column '(.*?)' cannot be null");
            Matcher m = p.matcher(message);
            while (m.find()) {
                String group = m.group(1);
                message = group + "不能为空";
            }
        }
        return message;
    }



    @ExceptionHandler(WtzzNoRecordException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    public ResponseBean<String> notFound(WtzzNoRecordException e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        return returnResponse(false, WtzzResponse.NO_RECORD, e.getMessage());
    }

    @ExceptionHandler(WtzzConstraintException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ResponseBean<String> constraintFail(WtzzConstraintException e) {
        logger.error("occurs error when execute method ,message {}", e.getMessage());
        if (logger.isErrorEnabled()) logger.error(e.getMessage(), e);
        return returnResponse(false, WtzzResponse.ILLEGAL_ARGUMENT, e.getMessage());
    }


}
